<script setup lang="ts">
import { CaretBottom } from '@element-plus/icons-vue'
import PanchaActivity from '../pancha-activity/index.vue'
import type { TableProps } from 'element-plus'

import type { PanchaInformation, FacilityActivityItem } from './type'

import { carbonInventoryApi } from '@/api'
import { TANPANCHA_CATEGORY_TYPE } from '@/constant/modules/tanpancha'

defineOptions({ name: 'AsyncInformation' })

const props = defineProps<{
  protocolCode: string
  pointId: number
  dataTime?: number | string
  templateId?: number
  readonly?: boolean
  isTplViewing?: boolean
}>()
const emit = defineEmits<{
  (e: 'clickOnAddActivity'): void
  (e: 'syncSummary', data: {
    totalCarbonEmission: number
    carbonEmission: number
    emissionReduction: number
  }): void
  (e: 'syncCarbonInventoryId', id: number): void
  (e: 'afterTemplateIdApplied'): void
}>()
type FA = PanchaInformation['dataList'][number]['categoryList'][number]['facilityActivityList']
type CategoryVo = PanchaInformation['dataList'][number]
type CategoryDetailVo = CategoryVo['categoryList'][number]
type SaveSubCategoryResult = Omit<CategoryVo, 'categoryList'> & {
  carbonInventoryId: number
}

const PREFIX = '类别'

const tanpanchaStore = useTanpanchaStore()
const { getPointNameById } = useUserStore()
const panchaActivityRef = ref<InstanceType<typeof PanchaActivity>>()
const activeNames = ref([])
const loading = ref(false)
const info = shallowRef({
  carbonInventoryId: null,
  totalCarbonEmission: null,
  carbonEmission: null,
  emissionReduction: null,
  status: null,
  dataList: [],
} as unknown as PanchaInformation)

// 盘查ID
const carbonInventoryId = ref()

const categoryName = ref('')
const subCategoryName = ref('')
// 小类ID
const categoryId = ref<number>()

// 活动ID
const activityId = ref()

// 同步盘查ID
watch(carbonInventoryId, (val) => {
  emit('syncCarbonInventoryId', val as number)
})

async function handleAddActivity(item: CategoryVo, itemIndex: number, child: CategoryDetailVo) {
  activityId.value = undefined
  categoryName.value = `${substringCategoryName(itemIndex)}：${item.name}`
  subCategoryName.value = child.name
  categoryId.value = child.id
  await nextTick()
  panchaActivityRef.value?.open()
  emit('clickOnAddActivity')
}

async function handleEditActivity(index: number, item: CategoryVo, child: CategoryDetailVo, row: FacilityActivityItem) {
  activityId.value = row.id
  categoryName.value = `${substringCategoryName(index)}：${item.name}`
  subCategoryName.value = child.name
  categoryId.value = child.id
  await nextTick()
  panchaActivityRef.value?.open()
  emit('clickOnAddActivity')
}

async function handleDeleteActivity(child: CategoryDetailVo, item: FacilityActivityItem) {
  if (item.id) {
    carbonInventoryApi.deleteCarbonInventoryActivityById(item.id).then(() => {
      ElMessage.success('操作成功')
      removeActivity(child.id, item.id)
    })
  }
}

function onActivitySaveSuccess(data: any) {
  ElMessage.success('操作成功')
  const { carbonInventoryId: _carbonInventoryId, id, categoryId } = data
  _carbonInventoryId && (carbonInventoryId.value = _carbonInventoryId)
  console.log('save successfully!', data)
  if (!id)
    return
  if (!activityId.value) {
    appendActivity(id, categoryId)
  }
  else {
    updateActivity(id, categoryId)
  }
  activityId.value = id
}

async function getActivityInfoById(id: number) {
  const { data } = await carbonInventoryApi.queryCarbonInventoryActivityDetailsById(id)
  return data
}

function getFAfromListByCategoryId(categoryId: number): FA | null {
  const dataList = info.value.dataList
  let target = null
  for (const categoryVo of dataList) {
    for (const categoryDetailVo of categoryVo.categoryList) {
      if (categoryDetailVo.id === categoryId) {
        target = categoryDetailVo.facilityActivityList
        break
      }
    }
  }
  return target as FA | null
}

function updateActivity(aId: number, categoryId: number) {
  const target = getFAfromListByCategoryId(categoryId)
  if (target) {
    getActivityInfoById(aId).then((data) => {
      const index = target.findIndex(item => item.id === aId)
      if (index !== -1) {
        target[index] = data as unknown as FA[number]
        triggerRef(info)
      }
    })
  }
}

function appendActivity(aId: number, categoryId: number) {
  const target = getFAfromListByCategoryId(categoryId)
  if (target) {
    getActivityInfoById(aId).then((data) => {
      target.push(data as unknown as FA[number])
      triggerRef(info)
    })
  }
}

function removeActivity(categoryId: number, aId: number) {
  const target = getFAfromListByCategoryId(categoryId)
  if (target) {
    const i = target.findIndex(v => v.id === aId)
    if (i > -1) {
      target.splice(i, 1)
      triggerRef(info)
    }
  }
}

async function getInfo() {
  loading.value = true
  await sleep(300)
  try {
    let data
    if (props.templateId) {
      let ciId
      if (!props.isTplViewing) {
        const res = await carbonInventoryApi.createCarbonInventoryByTemplateId({
          templateId: props.templateId,
          dataTime: props.dataTime as number,
        })
        // 模板创建盘查成功后返回了新建的盘查ID
        ciId = res.data.carbonInventoryId
        // 模板只能使用一次
        emit('afterTemplateIdApplied')
      }
      if (!ciId) {
        // 模板创建成功后，根据模板去拿盘查的快照
        const r = await carbonInventoryApi.loadCarbonInventorySnapshotByTemplateId(props.templateId)
        // 把新的盘查ID塞入到返回体中
        data = { ...r.data, carbonInventoryId: ciId }
      }
    }
    if (!props.isTplViewing) {
      const res = await carbonInventoryApi.queryCarbonInventory(
        {
          pointId: unref(props.pointId),
          dataTime: unref(props.dataTime) as number,
          protocolCode: unref(props.protocolCode),
        },
      )
      data = res.data
    }

    const { dataList, ...rest } = data

    const d = Math.floor(dataList.length / 3)
    info.value = {
      ...rest,
      dataList: dataList.slice(0, d),
    }
    setTimeout(() => {
      info.value = {
        ...rest,
        dataList,
      }
    }, 300)
    activeNames.value = data.dataList.map((item: any, index: number) => substringCategoryName(index))
    carbonInventoryId.value = data.carbonInventoryId
    emit('syncCarbonInventoryId', data.carbonInventoryId as number)
    emit('syncSummary', {
      totalCarbonEmission: data.totalCarbonEmission,
      carbonEmission: data.carbonEmission,
      emissionReduction: data.emissionReduction,
    })
  }
  catch (error) {
    console.error(error)
  }
  finally {
    loading.value = false
    await nextTick()
  }
}

function convertFacilityListToTableList(list: FA): FacilityActivityItem[] {
  const result: FacilityActivityItem[] = []
  for (const item of list) {
    const { gasList, ...rest } = item
    for (const { id, ...other } of gasList) {
      result.push({
        ...rest,
        ...other,
      })
    }
  }
  return result
}
function generateTableSpanMethod(list: FA): TableProps<FacilityActivityItem>['spanMethod'] {
  const properties = ['name', 'emissionSource', 'emissionType', 'yearNum', 'sourceType', 'unit', 'updateTime', 'k']
  // list转换后的第一个气体的行索引
  const lens = list.reduce((acc, cur) => {
    acc.push(cur.gasList.length)
    return acc
  }, [] as number[])
  // [3, 2, 2] => [3, 5, 7]
  const arrRowIndex = lens.reduce((acc, cur) => {
    const pre = acc[acc.length - 1] ?? 0
    acc = acc.concat([pre + cur])
    return acc
  }, [] as number[])
  // [3, 5, 7] => [0, 3, 5]
  arrRowIndex.unshift(0)
  arrRowIndex.pop()

  // console.log(lens)
  // console.log(arrRowIndex)

  return (param) => {
    const { column, rowIndex } = param
    if (properties.includes(column.property)) { // 行合并，合并的行数取决于温室气体的数量
      if (arrRowIndex.includes(rowIndex)) {
        const i = arrRowIndex.indexOf(rowIndex)
        return [lens[i], 1]
      }
      else {
        return [0, 0]
      }
    }
  }
}

function appendSubCategory(pid: number, item: SaveSubCategoryResult) {
  // 大类
  const category = info.value.dataList.find(item => item.id === pid)
  if (category) {
    // 小类集
    const subs = category.categoryList ?? []
    // 追加
    subs.push({
      id: item.id,
      name: item.name,
      xh: item.xh,
      categoryType: TANPANCHA_CATEGORY_TYPE.NEW,
      facilityActivityList: [],
    })
    triggerRef(info)
  }
}

function removeSubCategory(pid: number, id: number) {
  // 大类
  const category = info.value.dataList.find(item => item.id === pid)
  if (category) {
    // 小类集
    const subs = category.categoryList ?? []
    // 删除
    subs.splice(subs.findIndex(v => v.id === id), 1)
    triggerRef(info)
  }
}

async function handleAddCategory(item: CategoryVo) {
  const res = await ElMessageBox.prompt('请输入分类名称', '新增子类别', {
    inputErrorMessage: '请输入分类名称，不能超过50个字',
    inputPattern: /^.{1,50}$/,
  }).catch(() => {})
  if (res && res.value) {
    const params = {
      pointId: props.pointId,
      protocolCode: props.protocolCode,
      dataTime: props.dataTime as number,
      name: res.value,
      pid: item.id,
    }
    carbonInventoryApi.addCarbonInventorySubCategory(params).then(({ data }) => {
      // 更新盘查id
      info.value.carbonInventoryId = data.carbonInventoryId
      // 方便同步到父级组件
      carbonInventoryId.value = data.carbonInventoryId
      // 新增成功后，页面插入一个子类别
      appendSubCategory(params.pid, data)
    })
  }
}

function substringCategoryName(index: number) {
  return `${PREFIX}${index + 1}`
}

function substringSubCategoryName(index: number, childIndex: number) {
  return `${PREFIX}${index + 1}-${childIndex + 1}`
}

async function handleDeleteCategory(pid: number, item: CategoryVo['categoryList'][number]) {
  const carbonInventoryId = info.value.carbonInventoryId
  if (carbonInventoryId) {
    const params = {
      carbonInventoryId,
      categoryId: item.id,
    }
    carbonInventoryApi.deleteCarbonInventorySubCategory(params)
      .then(() => {
        // 删除成功后，页面移除一个子类别
        removeSubCategory(pid, item.id)
      })
  }
}

onMounted(async () => {
  // console.log(`
  //   protocolCode: ${props.protocolCode}
  //   pointId: ${props.pointId}
  //   dataTime: ${props.dataTime}
  // `)
  console.log('async mounted')
  registerClickHandle()
  await getInfo()
})
onUnmounted(() => {
  console.log('async unmounted')
  unregisterClickHandle()
})

function clickItemHandle(e: Event) {
  const wrapper = e.currentTarget as HTMLElement
  const target = e.target as HTMLElement
  if (target.classList.contains('carbon-inventory-category-item')) {
    wrapper.querySelectorAll('.carbon-inventory-category-item').forEach((item) => {
      (item as HTMLElement).style.color = 'inherit';
      (item as HTMLElement).style.opacity = '0.8'
    })
    target.style.color = 'var(--el-color-warning)'
    target.style.opacity = '1'

    const anchor = target.dataset.anchor
    if (anchor) {
      const anchorItem = document.querySelector(`[data-anchor-item="${anchor}"]`)
      anchorItem && (anchorItem as HTMLElement).scrollIntoView({
        behavior: 'smooth',
        block: 'start',
      })
    }
  }
}

function registerClickHandle() {
  const wrapper = document.querySelector('.carbon-inventory-category')
  if (!wrapper)
    return
  wrapper.addEventListener('click', clickItemHandle, false)
}

function unregisterClickHandle() {
  const wrapper = document.querySelector('.carbon-inventory-category')
  if (!wrapper)
    return
  wrapper.removeEventListener('click', clickItemHandle, false)
}
</script>

<template>
  <div
    v-loading="loading" element-loading-custom-class="global-loading"
    class="relative flex-auto overflow-auto before:absolute before:bottom-0 before:left-0 before:right-0 before:h-1px before:w-full before:bg-gray-5 before:opacity-40 before:content-['']"
  >
    <div class="h-full w-full flex overflow-hidden">
      <div class="carbon-inventory-category w-[279px] flex-shrink-0 overflow-auto p-3" style="scrollbar-width: none;">
        <ElCollapse v-model="activeNames">
          <ElCollapseItem
            v-for="(item, index) in info.dataList" :key="substringCategoryName(index)"
            :name="substringCategoryName(index)" class="whitespace-nowrap"
          >
            <template #title>
              <div class="max-w-[220px] overflow-hidden text-ellipsis whitespace-nowrap" :title="`${substringCategoryName(index)}：${item.name}`">
                {{ `${substringCategoryName(index)}：${item.name}` }}
              </div>
            </template>
            <ul v-if="item.categoryList" class="mb-0">
              <li v-for="(child, childIndex) in item.categoryList" :key="substringSubCategoryName(index, childIndex)">
                <div
                  class="carbon-inventory-category-item fs-14 cursor-pointer whitespace-normal py-3px opacity-80 transition-100 !hover:opacity-100"
                  :data-anchor="substringSubCategoryName(index, childIndex)"
                >
                  {{ `${substringSubCategoryName(index, childIndex)}：${child.name}` }}
                </div>
              </li>
            </ul>
          </ElCollapseItem>
        </ElCollapse>
      </div>
      <div class="w-1px bg-gray-5 opacity-40" />
      <div class="flex-1 overflow-auto p-3">
        <ElCollapse v-model="activeNames">
          <ElCollapseItem
            v-for="(item, index) in info.dataList" :key="substringCategoryName(index)" class="no-arrow-collapse-item"
            :name="substringCategoryName(index)" style="--el-collapse-header-bg-color: rgba(0,0,0,0.3);"
          >
            <template #title>
              <div class="fs-16 flex flex-auto items-center gap-2 px-3">
                <ElIcon>
                  <CaretBottom />
                </ElIcon>
                <div>
                  {{ `${substringCategoryName(index)}：${item.name}` }}
                </div>
                <ElButton v-if="!readonly" class="ml-auto" type="warning" plain size="small" @click.stop.prevent="handleAddCategory(item)">
                  新增子类别
                </ElButton>
              </div>
            </template>
            <div v-for="(child, childIndex) in item.categoryList" :key="substringSubCategoryName(index, childIndex)">
              <div class="p-3" :data-anchor-item="substringSubCategoryName(index, childIndex)">
                {{ `${substringSubCategoryName(index, childIndex)}：${child.name}` }}
                <ElTag v-if="!readonly && child.categoryType === TANPANCHA_CATEGORY_TYPE.NEW" size="small" type="danger" class="ml-3 cursor-pointer" @click.stop.prevent="handleDeleteCategory(item.id, child)">
                  删除
                </ElTag>
              </div>
              <ElTable
                :data="convertFacilityListToTableList(child.facilityActivityList)" size="small" border
                :span-method="generateTableSpanMethod(child.facilityActivityList)"
              >
                <ElTableColumn label="设施/活动" prop="name" />
                <ElTableColumn label="排放源" prop="emissionSource" />
                <ElTableColumn label="排放类型" prop="emissionType">
                  <template #default="scope">
                    {{ tanpanchaStore.getEmissionTypeText(scope.row.emissionType) }}
                  </template>
                </ElTableColumn>
                <ElTableColumn label="活动数据来源" prop="sourceType">
                  <template #default="scope">
                    {{ tanpanchaStore.getSourceTypeText(scope.row.sourceType) }}
                  </template>
                </ElTableColumn>
                <ElTableColumn label="活动数据年度值" prop="yearNum" />
                <ElTableColumn label="活动数据单位" prop="unit" />
                <ElTableColumn label="温室气体" prop="gas" />
                <ElTableColumn label="排放因子值" prop="emissionFactor" />
                <ElTableColumn label="排放因子单位" prop="emissionUnitFactor" />
                <ElTableColumn label="GWP值" prop="gwp" />
                <ElTableColumn label="换算比例" prop="discountValue" />
                <ElTableColumn label="修改时间" prop="updateTime" />
                <ElTableColumn v-if="!readonly" label="操作" width="100" prop="k" fixed="right">
                  <template #default="{ row }">
                    <ElLink class="free" type="primary" :underline="false" @click="handleEditActivity(index, item, child, row)">
                      编辑
                    </ElLink>
                    <ElLink class="free ml-2" type="danger" :underline="false" @click="handleDeleteActivity(child, row)">
                      删除
                    </ElLink>
                  </template>
                </ElTableColumn>
              </ElTable>
              <div v-if="!readonly" class="p-3">
                <ElLink class="free" :underline="false" type="primary" plain size="small" @click="handleAddActivity(item, index, child)">
                  + 添加设施/活动
                </ElLink>
              </div>
            </div>
          </ElCollapseItem>
        </ElCollapse>
      </div>
    </div>
  </div>
  <PanchaActivity
    v-if="categoryId && dataTime"
    ref="panchaActivityRef"
    :point-id="pointId" :protocol-code="protocolCode"
    :data-time="dataTime" :point-name="getPointNameById(pointId)"
    :category-name="categoryName"
    :sub-category-name="subCategoryName"
    :category-id="categoryId"
    :activity-id="activityId"
    :convert-facility-list-to-table-list="convertFacilityListToTableList"
    @save-success="onActivitySaveSuccess"
  />
</template>
